/**
 * 前端真实SM2/SM4加密工具库
 * 使用sm-crypto库实现真实的国密算法加密
 */

class CryptoUtils {
    
    // SM2公钥（从后端配置中获取）
    static SM2_PUBLIC_KEY = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAELxKvV0IjcGhdN+taKJPKxMhpG5maZT1MEXkRzFcXBr5I5MjRjkuGOX+XYwwByWM7aHOIr5BjT7O2JySDRfwxCQ==";
    
    /**
     * 生成随机SM4密钥（32位十六进制）
     */
    static generateSm4Key() {
        const chars = '0123456789abcdef';
        let result = '';
        for (let i = 0; i < 32; i++) {
            result += chars.charAt(Math.floor(Math.random() * chars.length));
        }
        return result;
    }
    
    /**
     * 使用SM2公钥加密SM4密钥
     */
    static encryptSm4Key(sm4Key, publicKey = this.SM2_PUBLIC_KEY) {
        try {
            // 将Base64格式的公钥转换为十六进制
            const publicKeyHex = this.base64ToHex(publicKey);
            
            // 使用SM2公钥加密SM4密钥
            const encrypted = sm2.doEncrypt(sm4Key, publicKeyHex);
            return encrypted;
        } catch (error) {
            console.error("SM4密钥加密失败:", error);
            throw new Error("SM4密钥加密失败: " + error.message);
        }
    }
    
    /**
     * 使用SM4密钥加密数据
     */
    static encryptData(data, sm4Key) {
        try {
            const jsonStr = JSON.stringify(data);
            
            // 使用SM4加密数据
            const encrypted = sm4.encrypt(jsonStr, sm4Key);
            return encrypted;
        } catch (error) {
            console.error("数据加密失败:", error);
            throw new Error("数据加密失败: " + error.message);
        }
    }
    
    /**
     * 使用SM4密钥解密数据
     */
    static decryptData(encryptedData, sm4Key) {
        try {
            // 使用SM4解密数据
            const decrypted = sm4.decrypt(encryptedData, sm4Key);
            return JSON.parse(decrypted);
        } catch (error) {
            console.error("数据解密失败:", error);
            throw new Error("数据解密失败: " + error.message);
        }
    }
    
    /**
     * 完整的加密流程
     */
    static encryptRequest(data) {
        try {
            // 1. 生成SM4密钥
            const sm4Key = this.generateSm4Key();
            console.log("生成的SM4密钥:", sm4Key);
            
            // 2. 使用SM4密钥加密数据
            const encryptedData = this.encryptData(data, sm4Key);
            console.log("加密后的数据:", encryptedData);
            
            // 3. 使用SM2公钥加密SM4密钥
            const encryptedKey = this.encryptSm4Key(sm4Key);
            console.log("加密后的密钥:", encryptedKey);
            
            return {
                encryptedData: encryptedData,
                encryptedKey: encryptedKey,
                sm4Key: sm4Key // 仅用于演示，实际不应该返回
            };
        } catch (error) {
            console.error("加密流程失败:", error);
            throw error;
        }
    }
    
    /**
     * 完整的解密流程
     */
    static decryptResponse(encryptedData, encryptedKey) {
        try {
            // 1. 使用SM2私钥解密SM4密钥（这里需要私钥，前端通常无法获取）
            // 2. 使用SM4密钥解密数据
            // 注意：前端通常无法进行SM2解密，因为私钥在后端
            console.warn("前端无法进行SM2解密，需要后端配合");
            return null;
        } catch (error) {
            console.error("响应解密失败:", error);
            return null;
        }
    }
    
    /**
     * Base64转十六进制
     */
    static base64ToHex(base64) {
        try {
            const binary = atob(base64);
            let hex = '';
            for (let i = 0; i < binary.length; i++) {
                const charCode = binary.charCodeAt(i);
                hex += charCode.toString(16).padStart(2, '0');
            }
            return hex;
        } catch (error) {
            console.error("Base64转十六进制失败:", error);
            throw error;
        }
    }
    
    /**
     * 十六进制转Base64
     */
    static hexToBase64(hex) {
        try {
            const bytes = new Uint8Array(hex.length / 2);
            for (let i = 0; i < hex.length; i += 2) {
                bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
            }
            const binary = String.fromCharCode.apply(null, bytes);
            return btoa(binary);
        } catch (error) {
            console.error("十六进制转Base64失败:", error);
            throw error;
        }
    }
    
    /**
     * UTF-8字符串转Base64
     */
    static utf8ToBase64(str) {
        try {
            const encoder = new TextEncoder();
            const bytes = encoder.encode(str);
            let binary = '';
            for (let i = 0; i < bytes.length; i++) {
                binary += String.fromCharCode(bytes[i]);
            }
            return btoa(binary);
        } catch (error) {
            console.error("UTF-8编码失败:", error);
            return btoa(unescape(encodeURIComponent(str)));
        }
    }

    /**
     * Base64转UTF-8字符串
     */
    static base64ToUtf8(base64) {
        try {
            const binary = atob(base64);
            const bytes = new Uint8Array(binary.length);
            for (let i = 0; i < binary.length; i++) {
                bytes[i] = binary.charCodeAt(i);
            }
            const decoder = new TextDecoder();
            return decoder.decode(bytes);
        } catch (error) {
            console.error("UTF-8解码失败:", error);
            try {
                return decodeURIComponent(escape(atob(base64)));
            } catch (e) {
                return atob(base64);
            }
        }
    }
    
    /**
     * 验证SM4密钥格式
     */
    static validateSm4Key(key) {
        if (!key || key.length !== 32) {
            throw new Error("SM4密钥长度必须为32个十六进制字符");
        }
        if (!/^[0-9a-fA-F]{32}$/.test(key)) {
            throw new Error("SM4密钥必须是有效的十六进制字符串");
        }
        return true;
    }
    
    /**
     * 测试加密解密功能
     */
    static testEncryption() {
        try {
            const testData = { message: "测试数据", timestamp: Date.now() };
            const sm4Key = this.generateSm4Key();
            
            console.log("测试数据:", testData);
            console.log("SM4密钥:", sm4Key);
            
            // 测试SM4加密解密
            const encrypted = this.encryptData(testData, sm4Key);
            console.log("加密结果:", encrypted);
            
            const decrypted = this.decryptData(encrypted, sm4Key);
            console.log("解密结果:", decrypted);
            
            // 测试SM2加密
            const encryptedKey = this.encryptSm4Key(sm4Key);
            console.log("SM2加密密钥:", encryptedKey);
            
            return true;
        } catch (error) {
            console.error("加密测试失败:", error);
            return false;
        }
    }
}

// 导出到全局
window.CryptoUtils = CryptoUtils;

// 页面加载完成后进行加密测试
document.addEventListener('DOMContentLoaded', function() {
    console.log("=== 加密工具库加载完成 ===");
    console.log("SM2公钥:", CryptoUtils.SM2_PUBLIC_KEY);
    
    // 测试加密功能
    if (typeof sm2 !== 'undefined' && typeof sm4 !== 'undefined') {
        console.log("SM2/SM4库加载成功");
        CryptoUtils.testEncryption();
    } else {
        console.error("SM2/SM4库加载失败");
    }
}); 